#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include <future>
#include <functional>

namespace rcrpc {
    namespace client {
        class Requestor {
            public:
                using ptr = std::shared_ptr<Requestor>;
                using RequestCallback = std::function<void(const BaseMessage::ptr&)>;
                using AsyncResponse = std::future<BaseMessage::ptr>;
                struct RequestDescribe {
                    using ptr = std::shared_ptr<RequestDescribe>;
                    BaseMessage::ptr request;
                    RType rtype;
                    std::promise<BaseMessage::ptr> response;
                    RequestCallback callback;
                };
                // 注册到dispatcher模块中
                void onResponse(const BaseConnection::ptr &conn, BaseMessage::ptr &msg){
                    std::string rid = msg->rid();
                    auto it = getDescribe(msg->rid());
                    if (it.get() == nullptr) {
                        ELOG("收到响应 - %s,但是未找到对应的请求描述！", rid.c_str());
                        return;
                    }
                    if ( it->rtype == RType::REQ_ASYNC) {
                        it->response.set_value(msg);
                    } else if(it->rtype == RType::REQ_CALLBACK) {
                        it->callback(msg);
                    } else {
                        ELOG(" id=%s 的未知的类型请求", msg->rid());
                    }

                    delDescribe(rid);
                }
                
                // 异步发送
                bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, AsyncResponse &async_rsp){
                    auto rd = newDescribe(req, RType::REQ_ASYNC);
                    if( rd.get() == nullptr) {
                        ELOG("构造请求描述对象失败！");
                        return false;
                    }
                    conn->send(rd->request); 
                    async_rsp = rd->response.get_future();
                    return true;
                }

                // 同步发送
                bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, BaseMessage::ptr &rsp){
                    AsyncResponse async_rsp;
                    bool ret = send(conn,req,async_rsp); 
                    if (ret == false) {
                        return false;
                    }
                    rsp = async_rsp.get();
                    return  true;
                }

                // 回调发送
                bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, RequestCallback &cb){
                    auto rd = newDescribe(req, RType::REQ_CALLBACK,cb);
                    if( rd.get() == nullptr) {
                        ELOG("构造请求描述对象失败！");
                        return false;
                    }
                    conn->send(rd->request);
                    return  true; 
                }
            private:
                // 创建一个请求对象
                RequestDescribe::ptr newDescribe(const BaseMessage::ptr &req, RType rtype,
                                 const RequestCallback &cb = RequestCallback()) {
                std::lock_guard<std::mutex> lock(_mutex);

                // 检查 req 是否为空
                if (!req) {
                    ELOG("传入req请求信息出现错误");
                    return nullptr; // 提前返回 nullptr 或抛出异常
                }

                auto rd = std::make_shared<RequestDescribe>();
                rd->request = req;
                rd->rtype = rtype;
                if (rtype == RType::REQ_CALLBACK) {
                    rd->callback = cb;
                }

                // 插入到映射表中
                _request_desc.insert(std::make_pair(req->rid(), rd));
                return rd;
            }

                // 获取请求
                RequestDescribe::ptr getDescribe(const std::string &id){
                    std::lock_guard<std::mutex> lock(_mutex);
                    auto it = _request_desc.find(id);
                    if (it == _request_desc.end()){
                        ELOG("获取 id = %s 请求失败", id);
                        return  RequestDescribe::ptr();
                    }
                    return it->second;
                }
                // 删掉请求
                void delDescribe(const std::string &id){
                    std::lock_guard<std::mutex> lock(_mutex);
                    auto it = _request_desc.find(id);
                    if (it == _request_desc.end()){
                        ELOG("清理 id = %s 请求失败", id);
                        return ;
                    }
                    _request_desc.erase(it);
                }
                std::mutex _mutex;
                std::unordered_map<std::string, RequestDescribe::ptr> _request_desc;
        };
    }
}